<?php
declare (strict_types=1);

namespace app\job\test;

use app\job\BaseJob;
use think\queue\Job;

/**
 * 队列消费者Demo:
 *
 * 运行方式:
 *  -- php think queue:listen --queue rxJobFirst
 *  -- php think queue:work --queue rxJobFirst
 */
class TestConsumer extends BaseJob
{
    /**
     * fire方法是消息队列默认调用的方法
     * @param Job $job 当前的任务对象
     * @param array $data 发布任务时自定义的数据
     */
    public function fire(Job $job, array $data)
    {
        // 有些任务在到达消费者时，可能已经不再需要执行了
        $isJobHasDone = $this->checkIfJobHasDone($data);
        if (!$isJobHasDone) {
            $job->delete();
            return;
        }

        //执行具体的业务逻辑
        $isJobDone = $this->doRunJob($data);

        //判断任务执行失败的次数,超过一定次数后从队列中删除,防止一直失败占用队列资源
        if (!$isJobDone) {
            echo "任务已经执行失败 " . $job->attempts() . "次 \n";
            if ($job->attempts() >= 3) {
                //todo 暂存数据库,等待后续人工介入后手动处理

                //删除队列中的数据
                $job->delete();
                echo "任务已执行失败 " . $job->attempts() . " 次,已暂存数据库,已从队列中删除 \n";
            }
            return;
        }

        //任务执行成功
        $job->delete();
        echo "任务执行成功,已从队列中删除\n";
    }

    /**
     * 有些消息在到达消费者时,可能已经不再需要执行了
     * @param array $data
     * @return bool
     */
    private function checkIfJobHasDone(array $data): bool
    {
        //todo 根据业务需求, 与当时写入队列时的数据校验

        return true;
    }

    /**
     * 根据消息中的数据进行实际的业务处理...
     * @param array $data
     * @return bool
     */
    private function doRunJob(array $data): bool
    {
        P('消费者获取到的队列内容:');
        P($data);

        //todo 接下来处理你的具体的业务逻辑...

        //返回执行结果
        return true;
    }
}
